import { BrowserModule, TransferState, Title } from "@angular/platform-browser";
import {
  NgModule,
  APP_INITIALIZER,
  LOCALE_ID,
  Injectable,
  PLATFORM_ID,
  APP_ID,
  Inject
} from "@angular/core";

import { FormsModule, ReactiveFormsModule, Validators } from "@angular/forms";
import {
  HttpClient,
  HttpClientModule,
  HTTP_INTERCEPTORS
} from "@angular/common/http";

import { AppComponent } from "./app.component";
import { RouterModule, Routes } from "@angular/router";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";

import { MatModule } from "@/mat/mat.module";

import { SwiperModule } from "./swiper/swiper.module";

import { HeaderComponent } from "./header/header.component";
import { FooterComponent } from "./footer/footer.component";
import { UserModule } from "./user/user.module";
import { LayoutModule } from "./layout/layout.module";

import { UserHeaderComponent } from "./user-header/user-header.component";

import { isPlatformBrowser, isPlatformServer } from "@angular/common";

import { environment } from "../environments/environment";
import { ValidatorsModule } from "@/validators/validators.module";

import { ApiModule } from "@/api/api.module";
import { CptsModule } from "@/cpts/cpts.module";

import { StoreRouterConnectingModule, routerReducer } from "@ngrx/router-store";
import { TransferHttpCacheModule } from "@nguniversal/common";

import {
  L10nModule,
  l10nConfig,
  LocalizationConfig,
  initLocalization
} from "@/l10n/l10n.module";

import { CookieModule, CookieService } from "ngx-cookie";

import { ShareModule } from "@/share/share.module";
import { AssetsModule } from "@/assets/assets.module";

import { MAT_SNACK_BAR_DEFAULT_OPTIONS } from "@angular/material/snack-bar";
import { MsgService } from "@/cpts/services/msg.service";

// mat
import { MATERIAL_SANITY_CHECKS } from "@angular/material";

import { MatPaginatorIntlService } from "@/mat/services/mat-paginator-intl.service";

// l10n
import {
  L10nConfig,
  L10nLoader,
  LocalizationModule,
  LocaleValidationModule,
  StorageStrategy,
  ProviderType,
  ISOCode,
  TranslationConfig,
  TRANSLATION_CONFIG
} from "angular-l10n";

// 账户记录
import { AccountService } from "@/share/services/account.service";

// pending
import { PendingService } from "@/share/services/pending.service";

// validators

import { HasUsernameValidatorService } from "@/validators/has-username-validator.service";
import { NoUsernameValidatorService } from "@/validators/no-username-validator.service";

// api
import { NoopInterceptorService } from "@/api/noop-interceptor.service";
import { StoreService } from "@/api/store.service";
import { TradeService } from "@/api/trade.service";
import { UserService } from "@/api/user.service";
import { RegService } from "@/api/reg.service";
import { EmailCodeService } from "@/api/email-code.service";
import { PhoneCodeService } from "@/api/phone-code.service";
import { UtilsService } from "@/api/utils.service";
import { ConfigService } from "@/api/config.service";
import { FileService } from "@/api/file.service";
import { GoodService } from "@/api/good.service";
import { SliderCodeService } from "@/api/slider-code.service";
import { SymbolService } from "@/api/symbol.service";
import { AssetsService } from "@/api/assets.service";
import { SkService } from "@/api/sk.service";
import { BugService } from "@/api/bug.service";
import { Base64Service } from "@/share/services/base64.service";

// router guard
import { AuthGuardService } from "@/share/services/auth-guard.service";

import { AppRoutingModule } from "./app-routing.module";

// fix angular mat bug
import { HAMMER_GESTURE_CONFIG } from "@angular/platform-browser";
import { GestureConfig } from "@angular/material";
import { MatPaginatorIntl } from "@angular/material";

// resolve
import { UserResolveService } from "@/share/services/user-resolve.service";

import { DialogService } from "@/cpts/services/dialog.service";

// store
import { TradeEffects } from "@/trade/store/effects/trade.effects";
import * as fromTrade from "@/trade/store/reducers";

import * as fromUser from "@/user/store/reducers";
import { UserEffects } from "@/user/store/effects/user.effects";

import * as fromMain from "@/main/store/reducers";
import { MainEffects } from "@/main/store/effects/main.effects";

import * as fromAssets from "@/assets/store/reducers";
import { AssetsEffects } from "@/assets/store/effects/assets.effects";

import { StoreModule } from "@ngrx/store";
import { EffectsModule } from "@ngrx/effects";
import { reducers } from "./reducers";
import { StoreDevtoolsModule } from "@ngrx/store-devtools";

@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    FooterComponent,
    UserHeaderComponent
  ],
  imports: [
    ApiModule,
    AppRoutingModule,
    LocalizationModule.forRoot(l10nConfig),
    // BrowserModule.withServerTransition({ appId: "eh" }),
    FormsModule,
    ReactiveFormsModule,
    HttpClientModule,
    BrowserAnimationsModule,
    MatModule,
    UserModule,
    LayoutModule,
    ValidatorsModule,
    CptsModule,
    TransferHttpCacheModule,
    CookieModule.forRoot(),
    ShareModule,
    AssetsModule,
    /**
     * StoreModule.forRoot is imported once in the root module, accepting a reducer
     * function or object map of reducer functions. If passed an object of
     * reducers, combineReducers will be run creating your application
     * meta-reducer. This returns all providers for an @ngrx/store
     * based application.
     */
    StoreModule.forRoot(reducers, {}),
    /**
     * @ngrx/router-store keeps router state up-to-date in the store.
     */
    StoreRouterConnectingModule.forRoot(),

    /**
     * Store devtools instrument the store retaining past versions of state
     * and recalculating new states. This enables powerful time-travel
     * debugging.
     *
     * To use the debugger, install the Redux Devtools extension for either
     * Chrome or Firefox
     *
     * See: https://github.com/zalmoxisus/redux-devtools-extension
     */
    StoreDevtoolsModule.instrument({
      name: "NgRx Book Store App",
      logOnly: environment.production
    }),

    EffectsModule.forRoot([
      TradeEffects,
      UserEffects,
      MainEffects,
      AssetsEffects
    ])

    /**
     * EffectsModule.forRoot() is imported once in the root module and
     * sets up the effects class to be initialized immediately when the
     * application starts.
     *
     * See: https://github.com/ngrx/platform/blob/master/docs/effects/api.md#forroot
     */
  ],
  providers: [
    { provide: MatPaginatorIntl, useClass: MatPaginatorIntlService },
    { provide: "BugService", useClass: BugService },
    { provide: "PendingService", useClass: PendingService },
    { provide: "Base64Service", useClass: Base64Service },
    { provide: "SkService", useClass: SkService },
    { provide: "TradeService", useClass: TradeService },
    { provide: "DialogService", useClass: DialogService },
    { provide: "UserResolveService", useClass: UserResolveService },
    // Angular material has a bug with the import order of browserModule and angular material which causes Hammger gestures to get overridden.
    { provide: HAMMER_GESTURE_CONFIG, useClass: GestureConfig },
    { provide: "AuthGuardService", useClass: AuthGuardService },
    { provide: "MsgService", useClass: MsgService },
    { provide: "AssetsService", useClass: AssetsService },
    { provide: MAT_SNACK_BAR_DEFAULT_OPTIONS, useValue: { duration: 2500 } },
    LocalizationConfig,
    {
      provide: APP_INITIALIZER,
      useFactory: initLocalization,
      deps: [LocalizationConfig],
      multi: true
    },
    {
      provide: MATERIAL_SANITY_CHECKS,
      useValue: false
    },
    { provide: "AccountService", useClass: AccountService },
    {
      provide: "CookieService",
      useClass: CookieService
    },
    {
      provide: "HasUsernameValidatorService",
      useClass: HasUsernameValidatorService
    },
    {
      provide: "NoUsernameValidatorService",
      useClass: NoUsernameValidatorService
    },
    { provide: "StoreService", useClass: StoreService },
    { provide: "RegService", useClass: RegService },
    { provide: "UserService", useClass: UserService },
    { provide: "EmailCodeService", useClass: EmailCodeService },
    { provide: "PhoneCodeService", useClass: PhoneCodeService },
    { provide: "UtilsService", useClass: UtilsService },
    { provide: "ConfigService", useClass: ConfigService },
    { provide: "FileService", useClass: FileService },
    { provide: "GoodService", useClass: GoodService },
    { provide: "SliderCodeService", useClass: SliderCodeService },
    { provide: "SymbolService", useClass: SymbolService },
    {
      provide: HTTP_INTERCEPTORS,
      useClass: NoopInterceptorService,
      multi: true
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
  constructor(
    @Inject(PLATFORM_ID) private platformId: Object,
    @Inject(APP_ID) private appId: string
  ) {
    const platform = isPlatformBrowser(platformId)
      ? "in the browser"
      : "on the server";
    console.log(`Running ${platform} with appId=${appId}`);
  }
}
